/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xq.gwt.mvc.controller;

import xq.gwt.mvc.model.PropertyChangedEvent;
import xq.gwt.mvc.model.PropertyChangedListener;
import xq.gwt.mvc.model.PropertyModel;
import xq.gwt.mvc.model.ReadOnlyChangedListener;
import xq.gwt.mvc.model.RequiredChangedListener;
import xq.gwt.mvc.view.PropertyView;
import xq.gwt.mvc.view.ViewChangedListener;

/**
 *
 * @author admin
 */
public abstract class AbstractPropertyController implements PropertyChangedListener, ViewChangedListener, ReadOnlyChangedListener, RequiredChangedListener {
   
	private static final long serialVersionUID = -6423949531797056343L;
	protected boolean blockPropertyChanged;
    protected PropertyView view;
    protected PropertyModel model;

    public AbstractPropertyController(PropertyView view){
        this.view = view;
        this.view.addViewChangedListener(this);
    }

    protected void setPropertyModel(PropertyModel model){
        if(this.model != null){
            this.model.removePropertyChangedListener(this);
            this.model.removeReadOnlyChangedListener(this);
            this.model.removeRequiredChangedListener(this);
        }

        this.model = model;
        updateViewNoNotification();
        if(this.model == null){
        	view.setEnabled(false);
            view.setRequired(false);        
            view.setTitle(null);
            view.clearError();
            return;
        }
        
        
        view.setEnabled(!this.model.isReadonly());
        validate();
        view.setRequired(this.model.isRequired());        
        view.setTitle(this.model.getTitle());        
        this.model.addPropertyChangedListener(this);
        this.model.addReadOnlyChangedListener(this);
        this.model.addRequiredChangedListener(this);
    }

    public void propertyChanged(PropertyChangedEvent event) {
        if(!blockPropertyChanged)
            updateViewNoNotification();
    }

    public void viewChanged(){
        if(!blockPropertyChanged)
            updateModelNoNotification();
    }

    public void readOnlyChanged(){
    	view.setEnabled(!this.model.isReadonly());
    }
    
    public void requiredChanged(){
    	view.setRequired(this.model.isRequired());
    }
    
    protected void updateModelNoNotification(){
        blockPropertyChanged = true;
        updateModel();
        blockPropertyChanged = false;

    }

    protected void updateViewNoNotification(){
        blockPropertyChanged = true;
        updateView();
        blockPropertyChanged = false;

    }
    
    public void validate(){
    	  if(model.getHasError()){
          	view.setError("Invalid value");          	
          } else{
        	  view.clearError();
          }        	  
    }

    public abstract void updateModel();

    public abstract void updateView();
    
    public PropertyModel getModel(){
    	return model;
    }
    
    public PropertyView getView(){
    	return view;
    }

}
